#include "StdAfx.h"
/*
	Implementation sources/help:
	DevIL: http://gpwiki.org/index.php/DevIL:Tutorials:Basics
*/
Texture::Texture(TextureDesc &desc):GameResource(desc)
{
	MagFilter=desc.MagFilter;
	MinFilter=desc.MinFilter;
	bGenerateMipmaps=desc.bGenerateMipmaps;
	bDepthCompare=desc.bDepthCompare;
	Width=desc.Width;
	Height=desc.Height;
	InternalFormat=desc.InternalFormat;
	Format=desc.Format;
	Target=desc.Target;
	Type=desc.Type;
	Resize(Width, Height);
}
Vec2 Texture::GetDimensions()
{
	return Vec2(Width, Height);
}
void Texture::Bind()
{
	glEnable(Target);
	glBindTexture(Target, TextureID);
}
void Texture::Unbind()
{
	glBindTexture(Target, 0);
	glDisable(Target);
}
void Texture::StoreFrame(unsigned int originx, unsigned int originy, unsigned int width, unsigned int height, unsigned int face_id, unsigned int level)
{
	Bind();
	if(IsCubeMap())
	{
		if(face_id>=0
			&&face_id<6)
			glCopyTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X+face_id,level,InternalFormat,originx,originy,width,height,0);
	}
	else glCopyTexImage2D(GL_TEXTURE_2D,level,InternalFormat,originx,originy,width,height,0);
	Unbind();
	_err("Failed to copy the frame into texture "<<Name);
}
Texture::~Texture(void)
{
	glDeleteTextures(1, &TextureID);
}
GLuint Texture::GetID()
{
	return TextureID;
}
bool Texture::IsCubeMap()
{
	return Target==GL_TEXTURE_CUBE_MAP;
}
void Texture::Resize(int width, int height)
{
	Width=width;
	Height=height;
	glDeleteTextures(1, &TextureID);
	GLuint newTextureID;
	glGenTextures(1, &newTextureID);
	TextureID=newTextureID;
    Bind();
	//define filtering
	/*glTexParameterf(Target, GL_TEXTURE_MAG_FILTER, MagFilter);
	glTexParameterf(Target, GL_TEXTURE_MIN_FILTER, MinFilter);*/
	glTexParameterf(Target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	if(bGenerateMipmaps)
		glTexParameterf(Target, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
	else glTexParameterf(Target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameterf(Target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameterf(Target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
	if(bDepthCompare)
	{
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_COMPARE_FUNC,GL_LEQUAL);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_COMPARE_MODE,GL_COMPARE_R_TO_TEXTURE);
	}
	if(IsCubeMap())
	{
		glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
		glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_EXT);
		glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_EXT);
		glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_EXT);
		glTexParameterf(Target, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
	}
	//should the mipmaps be generated?
	glTexParameteri(Target, GL_GENERATE_MIPMAP, bGenerateMipmaps);
	//if is cubemap init all 6 faces
	if(IsCubeMap())
		for(unsigned int i=0;i<6;i++)
			glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X+i, 0, InternalFormat, Width, Height, 0, Format, Type, 0);
	//else just the main texture
	else glTexImage2D(Target, 0, InternalFormat, Width, Height, 0, Format, Type, 0);
    Unbind();
	_err("Failed to [re]load the texture "<<Name);
}
void Texture::LoadFromFile()
{
	MagFilter=GL_LINEAR;
	MinFilter=GL_LINEAR_MIPMAP_LINEAR;
	bGenerateMipmaps=true;
	Target=GL_TEXTURE_2D;
	Type=GL_UNSIGNED_BYTE;

	ILuint imageID;
	ILboolean bresult;
	//generate and bind a new image
	ilGenImages(1, &imageID); 
	ilBindImage(imageID);
	//load the image
	bresult=ilLoadImage(FileName);
	//if failed to load
	if(!bresult)
		_err("Texture: file "<<FileName<<" couldn't be loaded.");
	//convert it to the desired color format
	bresult=ilConvertImage(IL_RGBA, IL_UNSIGNED_BYTE);
	//if failed to convert
	if(!bresult)
	{
		ilDeleteImages(1, &imageID);
		_err("Texture: could not convert "<<FileName<<" to proper color format");
	}
	Width=ilGetInteger(IL_IMAGE_WIDTH);
	Height=ilGetInteger(IL_IMAGE_HEIGHT);
	InternalFormat=ilGetInteger(IL_IMAGE_BPP);
	Format=ilGetInteger(IL_IMAGE_FORMAT);
	//generate and bind a new texture
	glGenTextures(1, &TextureID);
	if(TextureID==-1)
		_err("Texture: OpenGL could not generate a texture name.");
    Bind();
	//choose linear interpolation for both mag/min filters
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, MagFilter);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, MinFilter);
	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
	//transfer the IL image into a GL texture
    glTexImage2D(GL_TEXTURE_2D, 0, InternalFormat, Width,
      Height, 0, Format, Type, ilGetData());
	//free the IL image
	ilDeleteImages(1, &imageID);
	GenerateMipMaps();
	Unbind();
	_err("Failed to load the texture "<<Name<<" from file "<<FileName);
}
void Texture::GenerateMipMaps()
{
	if(bGenerateMipmaps)
	{
		if(IsCubeMap())
			glGenerateMipmap(GL_TEXTURE_CUBE_MAP);
		else glGenerateMipmap(GL_TEXTURE_2D);
	}
}
void Texture::SaveToFile()
{
}
